﻿// MedicalRulesEngine.Core/Extensions/ServiceCollectionExtensions.cs
using MedicalRulesEngine.Core.Mappings;
using MedicalRulesEngine.Core.Services;
using MedicalRulesEngine.Domain.Entities;
using MedicalRulesEngine.Infrastructure.Data;
using MedicalRulesEngine.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;


namespace MedicalRulesEngine.Core.Extensions;

/// <summary>
/// 服务集合扩展方法
/// 用于注册应用程序服务
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 添加医疗规则引擎服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddMedicalRulesEngine(this IServiceCollection services, IConfiguration configuration)
    {
        // 添加数据库上下文
        services.AddDbContext<RulesDbContext>(options =>
        {
            var connectionString = configuration.GetConnectionString("DefaultConnection");
            options.UseSqlServer(connectionString, sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                    maxRetryCount: 3,
                    maxRetryDelay: TimeSpan.FromSeconds(30),
                    errorNumbersToAdd: null);
            });

            // 开发环境启用敏感数据日志
            if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
            {
                options.EnableSensitiveDataLogging();
                options.EnableDetailedErrors();
            }
        });

        // 添加仓储服务
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddScoped<IRuleRepository, RuleRepository>();
        services.AddScoped<IRepository<FieldDefinition>, Repository<FieldDefinition>>();
        services.AddScoped<IRepository<OperatorDefinition>, Repository<OperatorDefinition>>();

        // 添加业务服务
        services.AddScoped<IRuleService, RuleService>();
        services.AddScoped<IMetadataService, MetadataService>();

        // 添加AutoMapper
        services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>());

        // 添加RulesEngine
        services.AddSingleton<RulesEngine.RulesEngine>();

        return services;
    }

    /// <summary>
    /// 添加医疗规则引擎服务（使用内存数据库）
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddMedicalRulesEngineInMemory(this IServiceCollection services)
    {
        // 添加内存数据库上下文
        services.AddDbContext<RulesDbContext>(options =>
        {
            options.UseInMemoryDatabase("MedicalRulesEngine");
            options.EnableSensitiveDataLogging();
            options.EnableDetailedErrors();
        });

        // 添加仓储服务
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddScoped<IRuleRepository, RuleRepository>();
        services.AddScoped<IRepository<FieldDefinition>, Repository<FieldDefinition>>();
        services.AddScoped<IRepository<OperatorDefinition>, Repository<OperatorDefinition>>();

        // 添加业务服务
        services.AddScoped<IRuleService, RuleService>();
        services.AddScoped<IMetadataService, MetadataService>();

        // 添加AutoMapper
        services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>());

        // 添加RulesEngine
        services.AddSingleton<RulesEngine.RulesEngine>();

        return services;
    }

    /// <summary>
    /// 初始化医疗规则引擎数据
    /// </summary>
    /// <param name="serviceProvider">服务提供者</param>
    /// <returns>异步任务</returns>
    public static async Task InitializeMedicalRulesEngineAsync(this IServiceProvider serviceProvider)
    {
        using var scope = serviceProvider.CreateScope();
        var context = scope.ServiceProvider.GetRequiredService<RulesDbContext>();
        var metadataService = scope.ServiceProvider.GetRequiredService<IMetadataService>();

        // 确保数据库已创建
        await context.Database.EnsureCreatedAsync();

        // 初始化默认元数据
        await metadataService.InitializeDefaultMetadataAsync();
    }
}
